package main

import (
	"reflect"
	"os"
	"fmt"
	"sync/atomic"
)

// 创建结构体，封装atomic.Value和村储值的合法类型
// 字段都是私有的，下面提供了4个可导出的方法
type atomicValue struct {
	v atomic.Value
	t reflect.Type
}

// 提供方法，返回存储值的合法类型
func (av *atomicValue) TypeOfValue() reflect.Type {
	return av.t
}

// 提供方法，存储值。存储之前先检查类型
func (av *atomicValue) Store(v interface{}) error {
	if v == nil {
		return fmt.Errorf("不能存储nil")
	}
	t := reflect.TypeOf(v)
	if t != av.t {
		return fmt.Errorf("类型不正确, 需要: %s, 实际: %s", av.t, t)
	}
	av.v.Store(v)
	return nil
}

// 提供方法，获取值，虽然示例中没有用到
func (av *atomicValue) Load() interface{} {
	return av.v.Load()
}

// 创建结构体的方法，相当于构造方法
func NewAtomicValue(x interface{}) (*atomicValue, error) {
	if x == nil {
		return nil, fmt.Errorf("不能存储nil")
	}
	return &atomicValue{
		t: reflect.TypeOf(x),  // 获取变量的类型，返回reflect.Type类型
	}, nil
}

func main() {
	v := fmt.Errorf("随便的错误")
	box, err := NewAtomicValue(v)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
	}
	fmt.Printf("合法的类型是: %s\n", box.TypeOfValue())
	v2 := fmt.Errorf("还是一个错误类型")
	err = box.Store(v2)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
	}
	fmt.Printf("存储了一个值，类型是: %T\n", v2)
	fmt.Println("尝试存储一个其他类型的值")
	err = box.Store(1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
	}
}